// Copyright (C) 2023 即时通讯网(52im.net) & Jack Jiang.
// The RainbowChat Project. All rights reserved.
// 
// 【本产品为著作权产品，合法授权后请放心使用，禁止外传！】
// 【本次授权给：<北京小羊驼科技有限公司>，授权编号：<NT231212144350>，代码指纹：<A.702363430.550>，技术对接人微信：<ID: wxid_wbyootvkdcgj22>】
// 【授权寄送：<收件：苏先生、地址：北京市大兴区北京密码西区6号楼1单元301、电话：18613885610、邮箱：bd@huiyuanxiang-inc.com>】
// 
// 【本系列产品在国家版权局的著作权登记信息如下】：
// 1）国家版权局登记名(简称)和权证号：RainbowChat    （证书号：软著登字第1220494号、登记号：2016SR041877）
// 2）国家版权局登记名(简称)和权证号：RainbowChat-Web（证书号：软著登字第3743440号、登记号：2019SR0322683）
// 3）国家版权局登记名(简称)和权证号：RainbowAV      （证书号：软著登字第2262004号、登记号：2017SR676720）
// 4）国家版权局登记名(简称)和权证号：MobileIMSDK-Web（证书号：软著登字第2262073号、登记号：2017SR676789）
// 5）国家版权局登记名(简称)和权证号：MobileIMSDK    （证书号：软著登字第1220581号、登记号：2016SR041964）
// * 著作权所有人：江顺/苏州网际时代信息科技有限公司
// 
// 【违法或违规使用投诉和举报方式】：
// 联系邮件：jack.jiang@52im.net
// 联系微信：hellojackjiang
// 联系QQ号：413980957
// 授权说明：http://www.52im.net/thread-1115-1-1.html
// 官方社区：http://www.52im.net
package com.x52im.rainbowchat.http.logic;

import java.util.HashMap;

import com.eva.epc.common.util.CommonUtils;
import com.eva.framework.dbpool.DBDepend;
import com.eva.framework.utils.LoggerFactory;
import com.x52im.rainbowchat.BaseConf;
import com.x52im.rainbowchat.http.concurrent.MailSendConcurrentExecutor;
import com.x52im.rainbowchat.http.logic.dto.RosterElementEntity;
import com.x52im.rainbowchat.http.util.OutgoingMail;

public class LogicUtils
{
	/**
	 * 异步发送邮件。
	 * 
	 * @param emailAddr 收件邮箱
	 * @param title 邮件标题
	 * @param content 邮件内容
	 */
	public static void sendMailAsync(final String emailAddr, final String title
			, final String content, final String logTag)
	{
		// 邮件发送是个缓慢的过程，为了不影响接口调用者的体验，所以用异步线程发送
		MailSendConcurrentExecutor.getInstance().execute(new Runnable(){
			@Override
			public void run()
			{
				OutgoingMail om = new OutgoingMail(
						BaseConf.getInstance().getSNS_INVITE_SMTP_SERVER()
						, BaseConf.getInstance().getSNS_INVITE_MASTER_EMAIL_ADDR()
						, BaseConf.getInstance().getSNS_INVITE_MASTER_NICK_NAME()
						, BaseConf.getInstance().getSNS_INVITE_MASTER_EMAIL_NAME()
						, BaseConf.getInstance().getSNS_INVITE_MASTER_EMAIL_PASSWORD()
						, emailAddr
						, title
						, content
						, BaseConf.getInstance().getSNS_INVITE_SMTP_PORT()
						, BaseConf.getInstance().getSNS_INVITE_SMTP_SSL());
//				om.addAttachfile("C:\\js4713.txt");

				boolean sendSucess = false;
				HashMap hm = null;
				try
				{
					// 发送邮件
					hm = om.send();
					if(hm.get("message")!=null)//发送成功了
						sendSucess = true;
				}
				catch (Exception e)
				{
					LoggerFactory.getLog().debug("[HTTP]异步发送"+logTag+"邮件时出错了，", e);
				}
				
				if(sendSucess)
					LoggerFactory.getLog().debug("[HTTP]发送给"+emailAddr+"的"+logTag+"邮件异步发送完成了."
							+(hm != null ?hm.get("message"):""));
				else
					LoggerFactory.getLog().warn("[HTTP]发送给"+emailAddr+"的"+logTag+"邮件异步发送失败了！"
							+(hm != null ?hm.get("state"):""));
			}
		});
	}
	/**
	 * 插入一条数据到“用户2进制资源”表中.
	 * 
	 * @param user_uid
	 * @param usedForPhoto true表示本次上传的资源是用户照片，否则是自我介绍语音文件
	 * @param res_file_name
	 * @param res_size
	 * @throws Exception
	 */
	public static void inserUsersBinary(String user_uid, boolean usedForPhoto
			, String res_file_name, long res_size) throws Exception
	{
		LogicProcessor2.db.update(
				"INSERT INTO missu_users_binary(user_uid,res_type,res_file_name,res_human_size,res_size,create_time) " +
				"VALUES(?,?,?,?,?, "+DBDepend.getDefaultDatetimeFunc()+")"
				, new Object[]{user_uid, usedForPhoto?"0":"1", res_file_name, CommonUtils.getConvenientFileSize(res_size, 2), res_size}
				, false);
	}
	
	/**
	 * 更新查看的资源文件的查看次数+1.
	 * <p>
	 * 目前APP里的实现：在客户端有缓存的情况下，是不会下载的，所以只在首次查看该相片
	 * 时才+1，此值也可以理解为被下载了多少次。
	 * <p>FIXME: 因调用本方法来自通用方法，因而目前更新条件只能用filename的方式，
	 * 如果用户（可能是不同的用户）上传上相同的文件（md5一样）情况下，则相同的文件的查看数都会+1，
	 * 目前暂时无法精确到客户端查看的某文件。不过好在此查看次数仅用于后台分析用户行为
	 * ，并无太大作用，目前就这样吧。
	 * 
	 * @param f
	 * @param res_file_name
	 * @throws Exception
	 */
	public static void increaseBinaryViewCount(String res_file_name) throws Exception
	{
		LogicProcessor2.db.update("update missu_users_binary set view_count=view_count+1 where res_file_name=?"
				, new Object[]{res_file_name}, false);
	}
	
	/**
	 * 查询用户信息(使用uid).
	 * 
	 * @param uidOfFriend
	 * @param myUid 查询发起人的uid，这个uid指的是客户端提起这个查询时的当前登陆者uid
	 * 				，指明此uid后本sql将同时提供被查询作为好友的额外信息。本参数可为null（表示不需要查询好友的额外信息）
	 * @return
	 * @throws Exception
	 */
	public static RosterElementEntity queryUserInfoByUID(String uidOfFriend, String myUid) throws Exception
	{
		return queryUserInfo(false, null , uidOfFriend, myUid);
	}
	/**
	 * 查询用户信息(使用邮件地址).
	 * 
	 * @param mailOfFriend
	 * @param myUid 查询发起人的uid，这个uid指的是客户端提起这个查询时的当前登陆者uid
	 * 				，指明此uid后本sql将同时提供被查询作为好友的额外信息。本参数可为null（表示不需要查询好友的额外信息）
	 * @return
	 * @throws Exception
	 */
	public static RosterElementEntity queryUserInfo(String mailOfFriend, String myUid) throws Exception
	{
		return queryUserInfo(true, mailOfFriend , null, myUid);
	}
	/**
	 * 查询用户信息.
	 * 
	 * @param useMail true表示使用U友的email查询，否则表示用uid查询
	 * @param mailOfFriend
	 * @param uidOfFriend
	 * @param myUid 查询发起人的uid，这个uid指的是客户端提起这个查询时的当前登陆者uid
	 * 				，指明此uid后本sql将同时提供被查询作为好友的额外信息。本参数可为null（表示不需要查询好友的额外信息）
	 * @return
	 * @throws Exception
	 */
	public static RosterElementEntity queryUserInfo(boolean useMail
			, String mailOfFriend, String uidOfFriend, String myUid) throws Exception
	{
		String baseSql = getUSER_INFI_BASE_SQL(myUid);

		String[] userInfoItems = null;
		// 使用好友的mail地址查找信息
		if(useMail)
			userInfoItems = LogicProcessor2.db.querySingleRowItems(baseSql+" where " +
//					"user_status = 1 and " +
					"user_mail = '"+mailOfFriend+"'");
		// 否则使用好友的uid查找信息
		else
			userInfoItems = LogicProcessor2.db.querySingleRowItems(baseSql+" where " +
//					"user_status = 1 and " +
					"user_uid = '"+uidOfFriend+"'");
		return constructUserInfo(userInfoItems);
	}
	
	public static RosterElementEntity constructUserInfo(Object[] userInfoItems)
	{
		RosterElementEntity friendInfoForFound = null;
		// 查找到了好友信息
		if(userInfoItems != null)
		{
			friendInfoForFound = new RosterElementEntity();
			int i = 0;
			friendInfoForFound.setUser_uid((String)userInfoItems[i++]);
			friendInfoForFound.setUser_mail((String)userInfoItems[i++]);
			friendInfoForFound.setNickname((String)userInfoItems[i++]);
			friendInfoForFound.setUser_sex((String)userInfoItems[i++]);
			friendInfoForFound.setRegister_time((String)userInfoItems[i++]);
			friendInfoForFound.setLatest_login_time((String)userInfoItems[i++]);
			i++;//查询条件中已包含密码,不进行Set
			friendInfoForFound.setLiveStatus(Integer.valueOf((String)userInfoItems[i++]));
			friendInfoForFound.setUserAvatarFileName((String)userInfoItems[i++]);
			friendInfoForFound.setWhatsUp((String)userInfoItems[i++]);
			
			friendInfoForFound.setMaxFriend((String)userInfoItems[i++]);
			friendInfoForFound.setUserDesc((String)userInfoItems[i++]);
			friendInfoForFound.setUserType((String)userInfoItems[i++]);
			
			friendInfoForFound.setLatest_login_ip((String)userInfoItems[i++]);
			
			friendInfoForFound.setFriendRemark((String)userInfoItems[i++]);
			friendInfoForFound.setFriendMobileNum((String)userInfoItems[i++]);
			friendInfoForFound.setFriendMoreDesc((String)userInfoItems[i++]);
			friendInfoForFound.setFriendPicFileName((String)userInfoItems[i++]);
		}
		return friendInfoForFound;
	}
	
	/**
	 * 返回用户信息查询SQL。
	 * 
	 * @param myUid 查询发起人的uid，这个uid指的是客户端提起这个查询时的当前登陆者uid
	 * 				，指明此uid后本sql将同时提供被查询作为好友的额外信息。本参数可为null（表示不需要查询好友的额外信息）
	 * @return
	 */
	public static String getUSER_INFI_BASE_SQL(String myUid) 
	{
		boolean myUidNull = (myUid == null);
		
		return "select " +
	
				// ============================= 请确保以下字段的数量、顺序与方法constructUserInfo是严格一致的！  START
				"	user_uid" +
				"	,user_mail" +
				"	,nickname" +
				"	,user_sex" +
				"	,register_time" +
				"	,latest_login_time2" + // 自20140109(KChat2.0以后版本)起取的值由latest_login_time改为了latest_login_time2
				"	,user_psw" +
				"	,is_online" +
				"	,user_avatar_file_name" +
				"	,what_s_up" +
				"	,max_friend" +         // 自20140109(KChat2.0以后版本)起启用
				"	,user_desc" +          // 自20140401(KChat2.5及以后版本)起启用
				"	,user_type" +          // 自20140417(KChat2.5.1及以后版本)起启用
				"	,latest_login_ip" +    // 自20181224(RainbowChat4.5及以后版本)起启用
				
				// 如果提供了查询发起人的（也就是myUid参数）uid，会同时查询该指定用户作为该发起人的好友的额外信息
				// 查询性能说明：其实为了查出这些额外信息可以通过一个子查询并left join完成，但为了降低SQL阅读的复杂性
				//				，采用了4个子查询，好在数据库表中已添加唯一索引，所以查询性能影响不大
				"	," +(myUidNull?"null":"(select remark from missu_roster where user_uid='"+myUid+"' and friend_user_uid=a.user_uid) as remark")+
				"	," +(myUidNull?"null":"(select mobile_num from missu_roster where user_uid='"+myUid+"' and friend_user_uid=a.user_uid) as mobile_num")+
				"	," +(myUidNull?"null":"(select more_desc from missu_roster where user_uid='"+myUid+"' and friend_user_uid=a.user_uid) as more_desc")+
				"	," +(myUidNull?"null":"(select pic_file_name from missu_roster where user_uid='"+myUid+"' and friend_user_uid=a.user_uid) as pic_file_name")+
				// ============================= 请确保以下字段的数量、顺序与方法constructUserInfo是严格一致的！  END
			
			" from missu_users a ";
	}	
	
	/**
	 * 返回用户信息查询SQL（支持分页、随机等）。
	 * 
	 * @param myUid 查询发起人的uid，这个uid指的是客户端提起这个查询时的当前登陆者uid
	 * 				，指明此uid后本sql将同时提供被查询作为好友的额外信息。本参数可为null（表示不需要查询好友的额外信息）
	 * @return
	 */
	public static String getUSER_INFI_RANDOM_SQL(String myUid)
	{
		return	"select {0}" +
				// ============================= 请确保以下字段的数量、顺序与方法constructUserInfo是严格一致的！  START
				"	user_uid" +
				"	,user_mail" +
				"	,nickname" +
				"	,user_sex" +
				"	,register_time" +
				"	,latest_login_time2" + // 自20140109(KChat2.0以后版本)起取的值由latest_login_time改为了latest_login_time2
				"	,user_psw" +
				"	,is_online" +
				"	,user_avatar_file_name" +
				"	,what_s_up" +
				"	,max_friend" +         // 自20140109(KChat2.0以后版本)起启用
				"	,user_desc" +          // 自20140401(KChat2.5及以后版本)起启用
				"	,user_type" +          // 自20140417(KChat2.5.1及以后版本)起启用
				"	,latest_login_ip" +    // 自20181224(RainbowChat4.5及以后版本)起启用
				
				//如果提供了查询发起人的（也就是myUid参数）uid，会同时查询该指定用户作为该发起人的好友的额外信息
				// 查询性能说明：其实为了查出这些额外信息可以通过一个子查询并left join完成，但为了降低SQL阅读的复杂性
				//				，采用了4个子查询，好在数据库表中已添加唯一索引，所以查询性能影响不大
				"	,(select remark from missu_roster where user_uid='"+myUid+"' and friend_user_uid=a.user_uid) as remark"+
				"	,(select mobile_num from missu_roster where user_uid='"+myUid+"' and friend_user_uid=a.user_uid) as mobile_num"+
				"	,(select more_desc from missu_roster where user_uid='"+myUid+"' and friend_user_uid=a.user_uid) as more_desc"+
				"	,(select pic_file_name from missu_roster where user_uid='"+myUid+"' and friend_user_uid=a.user_uid) as pic_file_name"+
				// ============================= 请确保以下字段的数量、顺序与方法constructUserInfo是严格一致的！  END
				
				// “order by newid()” 表示随机排序
				" from missu_users a"+ // a 是表的别名
				" where user_status = 1 and user_uid != {1}{2}{3} order by {4}";
	}
	
	/**
	 * 查询指定uid用户的邮件地址.
	 * 
	 * <p>系统中，用户的邮件地址与uid一样，拥有全局唯一性。
	 * 
	 * @param uid
	 * @return
	 * @throws Exception
	 */
	public static String queryUserMail(String uid) throws Exception
	{
		return LogicProcessor2.db.querySingleItem("select user_mail from missu_users where user_uid="+uid);
	}
	
	/**
	 * 查询指定人员的好友数量情况.
	 * 
	 * @param uid
	 * @return 存在该人员的信息则返回的是1维数组（2个单元，单元0是该人员允许的最大好友数、单元1是当前好友总数），否则返回null
	 * @throws Exception
	 */
	public static String[] queryUserFriendCount(String uid) throws Exception
	{
		if(uid == null)
			return null;
		
		StringBuffer sb = new StringBuffer();
		sb.append("select a.max_friend,b.current_friend_count from")
			.append("(")
			.append("	select max_friend from missu_users where user_uid="+uid+"")
			.append(") a ")
			.append("left join")
			.append("( ")
			.append("	select count(user_uid) as current_friend_count from missu_roster where user_uid="+uid+"")
			.append(") b on 1=1 ");
		String[] queryResult = LogicProcessor2.db.querySingleRowItems(sb.toString());
		return queryResult;
	}
	
	
	
//	/**
//	 * 登陆密码验证.
//	 * 
//	 * @param uidOrMail
//	 * @param password
//	 * @return
//	 * @throws Exception
//	 */
//	public static boolean userAuthentication(String uidOrMail, String password) throws Exception
//	{
//		// 登陆密码验证
//		return db.queryData("select 1 from missu_users" +
//				" where user_status = 1" +
//				" 	and (ltrim(str(user_uid))='"+uidOrMail+"' or user_mail='"+uidOrMail+"')"
////				+" 	and user_psw='"+password+"'"
//				).size() > 0;
//	}
}
